package dd.lo.chapter5;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.ByteArrayInputStream;
import java.util.Date;

/**
 * 对应程序示例
 * Example 5-1. Complete program to alpha-blend the ROI starting at (0,0) in src2 with the ROI starting at (x,y) in src1
 */
public class Example1 extends Application {
    private ImageView imageView;

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        int w = 1200, h = 900;
        imageView = new ImageView();
        imageView.setFitWidth(w);
        imageView.setFitHeight(h);
        //imageView放到一个pane的中间
        BorderPane root = new BorderPane();
        root.setCenter(imageView);
        Scene scene = new Scene(root, w, h);
        scene.setOnKeyReleased(keyEvent -> {
            //按下esc可以关闭程序
            if (KeyCode.ESCAPE == keyEvent.getCode()) {
                stage.close();
            }
        });
        stage.setScene(scene);
        stage.setTitle("C5E1-Alpha Blend");
        stage.setResizable(false);
        asyncDoAlphaBlend(w, h);
        stage.show();
    }

    private void asyncDoAlphaBlend(int w, int h) {
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                long startTime = new Date().getTime();
                //ROI区域大小，这里随便先弄个二分之一
                int hw = w / 2, hh = h / 2;
                //读取两张图片，需要做AlphaBlend的话，两张图片需要一样大小，所以先各resize一下
                Mat img1 = Imgcodecs.imread("/Users/kwok/Downloads/男女骑友.png", Imgcodecs.IMREAD_UNCHANGED);
                if (img1.empty()) {
                    throw new RuntimeException("图片读取失败");
                }
                Imgproc.resize(img1, img1, new Size(w, h));
                Mat img2 = Imgcodecs.imread("/Users/kwok/Downloads/约好的队友.png", Imgcodecs.IMREAD_UNCHANGED);
                if (img2.empty()) {
                    throw new RuntimeException("图片读取失败");
                }
                Imgproc.resize(img2, img2, new Size(hw, hh));
                //设置img1的ROI区域，这里得出的roi的内存地址其实还是映射到img1上面的
                int randX = (int) (Math.random() * hw);
                int randY = (int) (Math.random() * hh);
                Mat roi = new Mat(img1, new Rect(randX, randY, hw, hh));
                //Alpha blend for ROI(Region Of Interest)，注意进行AlphaBlend操作的两个图片大小一定要相同
                double alpha = 0.5, beta = 1 - alpha;
                Core.addWeighted(roi, alpha, img2, beta, 0, roi);
                MatOfByte buffer = new MatOfByte();
                Imgcodecs.imencode(".jpeg", img1, buffer);
                Platform.runLater(() -> imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray()))));
                System.out.printf("Alpha blend time consume: %d ms.\n", new Date().getTime() - startTime);
                return null;
            }
        };
        new Thread(task).start();
    }
}
